/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.thinkgem.jeesite.common.utils.excel;

import com.csvreader.CsvWriter;
import com.google.common.collect.Lists;
import com.thinkgem.jeesite.common.utils.Encodes;
import com.thinkgem.jeesite.common.utils.Reflections;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.utils.excel.annotation.ExcelField;
import com.thinkgem.jeesite.modules.sys.utils.DictUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

/**
 * 导出CSV文件
 * @author LTY
 * @version 2018-03-21
 */
public class ExportCSV {
	
	private static Logger log = LoggerFactory.getLogger(ExportCSV.class);
	
	
	/**
	 * 当前行号
	 */
	protected int rownum;
	
	/**
	 * 注解列表（Object[]{ ExcelField, Field/Method }）
	 */
	List<Object[]> annotationList = Lists.newArrayList();
	
	List<String> headerList = Lists.newArrayList();
	
	List<String[]> dataList = Lists.newArrayList();


	/**
	 * 构造函数
	 * @param title 表格标题，传“空值”，表示无标题
	 * @param cls 实体对象，通过annotation.ExportField获取标题
	 */
	public ExportCSV(String title, Class<?> cls){
		this(cls, 1);
	}
	/**
	 * 无参构造函数
	 */
	public ExportCSV(){
		
	}
	
	/**
	 * 构造函数
	 * @param cls 实体对象，通过annotation.ExportField获取标题
	 * @param type 导出类型（1:导出数据；2：导出模板）
	 * @param groups 导入分组
	 */
	public ExportCSV(Class<?> cls, int type, int... groups){
		// Get annotation field 
		Field[] fs = cls.getDeclaredFields();
		for (Field f : fs){
			ExcelField ef = f.getAnnotation(ExcelField.class);
			if (ef != null && (ef.type()==0 || ef.type()==type)){
				if (groups!=null && groups.length>0){
					boolean inGroup = false;
					for (int g : groups){
						if (inGroup){
							break;
						}
						for (int efg : ef.groups()){
							if (g == efg){
								inGroup = true;
								annotationList.add(new Object[]{ef, f});
								break;
							}
						}
					}
				}else{
					annotationList.add(new Object[]{ef, f});
				}
			}
		}
		// Get annotation method
		Method[] ms = cls.getDeclaredMethods();
		for (Method m : ms){
			ExcelField ef = m.getAnnotation(ExcelField.class);
			if (ef != null && (ef.type()==0 || ef.type()==type)){
				if (groups!=null && groups.length>0){
					boolean inGroup = false;
					for (int g : groups){
						if (inGroup){
							break;
						}
						for (int efg : ef.groups()){
							if (g == efg){
								inGroup = true;
								annotationList.add(new Object[]{ef, m});
								break;
							}
						}
					}
				}else{
					annotationList.add(new Object[]{ef, m});
				}
			}
		}
		// Field sorting
		Collections.sort(annotationList, new Comparator<Object[]>() {
			public int compare(Object[] o1, Object[] o2) {
				return new Integer(((ExcelField)o1[0]).sort()).compareTo(
						new Integer(((ExcelField)o2[0]).sort()));
			};
		});
		// Initialize
		
		for (Object[] os : annotationList){
			String t = ((ExcelField)os[0]).title();
			// 如果是导出，则去掉注释
			if (type==1){
				String[] ss = StringUtils.split(t, "**", 2);
				if (ss.length==2){
					t = ss[0];
				}
			}
			this.headerList.add(t);
		}
		
//		initialize(title, headerList);
//		exportCsv(file, headerList, dataList);
	}
	
	/**
	 * 构造函数
	 * @param title 表格标题，传“空值”，表示无标题
	 * @param headers 表头数组
	 */
	public ExportCSV(String[] headers) {
		
	}
	
	/**
	 * 构造函数
	 * @param headerList 表头列表
	 */
	public ExportCSV(List<String> headerList) {
		
	}
	/**
	 * 添加数据（通过annotation.ExportField添加数据）
	 * @return list 数据列表
	 */
	public <E> ExportCSV setDataList(List<E> list){
		for (int i=0; i<list.size(); i++){
			E e = list.get(i);
			int colunm = 0;
			
			StringBuilder sb = new StringBuilder();
			int annotationSize = annotationList.size();
			String[] dataArray = new String[annotationSize];
			for (int j=0; j<annotationSize; j++){
				Object[] os = annotationList.get(j);
				ExcelField ef = (ExcelField)os[0];
				Object val = null;
				// Get entity value
				try{
					if (StringUtils.isNotBlank(ef.value())){
						val = Reflections.invokeGetter(e, ef.value());
					}else{
						if (os[1] instanceof Field){
							val = Reflections.invokeGetter(e, ((Field)os[1]).getName());
						}else if (os[1] instanceof Method){
							val = Reflections.invokeMethod(e, ((Method)os[1]).getName(), new Class[] {}, new Object[] {});
						}
					}
					// If is dict, get dict label
					if (StringUtils.isNotBlank(ef.dictType())){
						val = DictUtils.getDictLabel(val==null?"":val.toString(), ef.dictType(), "");
					}
				}catch(Exception ex) {
					// Failure to ignore
					log.info(ex.toString());
					val = "";
				}
				
				if(val == null){
					dataArray[j] = "";
				}else{
					if(val instanceof Date) {
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						val = sdf.format(val);
					}
				}
				
				dataArray[j] = StringUtils.toString(val, "");
//				this.addCell(row, colunm++, val, ef.align(), ef.fieldType(),false);
				sb.append(val + ", ");
			}
			this.dataList.add(dataArray);
			log.debug("Write success: ["+i+"] "+sb.toString());
		}
		return this;
	}
	
	
	/**
	 * 输出到文件
	 * @param fileName 输出文件名
	 */
	public ExportCSV writeFile(String csvFilePath) throws FileNotFoundException, IOException {
		 try {  
	        // 创建CSV写对象 例如:CsvWriter(文件路径，分隔符，编码格式);  
	        CsvWriter csvWriter = new CsvWriter(csvFilePath, ',', Charset.forName("UTF-8"));
	        // 写表头  
	        String[] csvHeaders = this.headerList.toArray(new String[0]);
	        csvWriter.writeRecord(csvHeaders);
	        // 写内容  
	        for (int i=0; i<this.dataList.size(); i++) {  
	            csvWriter.writeRecord(dataList.get(i));  
	        }
	        csvWriter.close();  
	        System.out.println("--------CSV文件已经写入--------");
	    } catch (IOException e) {
	        e.printStackTrace();  
	    }
		return this;
	}
	
	/**
	 * 输出到客户端
	 * @param fileName 输出文件名
	 */
	public ExportExcel write(HttpServletResponse response, String fileName) throws IOException {
			java.io.OutputStream out = response.getOutputStream();
			byte[] b = new byte[10240];  
			File fileLoad = new File(fileName);
			response.reset();  
			response.setContentType("application/csv");    
			response.setHeader("Content-Disposition", "attachment; filename="+ Encodes.urlEncode(fileName));
			long fileLength = fileLoad.length();
			String length1 = String.valueOf(fileLength);
			response.setHeader("Content_Length", length1);
			FileInputStream in = new FileInputStream(fileLoad);
			int n;    
			while ((n = in.read(b)) != -1) {    
			 out.write(b, 0, n); //每次写入out1024字节   
			}    
			in.close();
			out.close();
			return null;  
	} 


}
